package life;

import java.util.ArrayList;

public class Liso_0_1
{
	double dailyEnergyConsume = 2;
	double energy = 200;
	Coordinate position;
	Coordinate vel; // just the direction NOT the vector
	double radiusPeception;// radius of the perception
	double perception;// probability to spot something inside the radius
						// Perception
	double age = 0;
	double lisoLifeSpan;
	double fertility;

	public Liso_0_1(World world, double lisoLifeSpan)
	{
		this.position = new Coordinate(Coordinate.RANDOM, world);
		this.vel = new Coordinate(Coordinate.VELOCITY, 1);
		this.radiusPeception = 80;
		this.perception = .8;
		this.lisoLifeSpan = lisoLifeSpan;
		this.fertility = 0.1;
	}

	public void aged()
	{
		age++;
		energy = energy - dailyEnergyConsume;
		// calucalate fertility
	}

	public boolean isStillAlive()
	{
		if (age < lisoLifeSpan && hasEnergy())
			return true;

		double deathProbability = 1.0 - 1.0 / (age - lisoLifeSpan + 1); // 1+1/(x+1)

		if (Math.random() > deathProbability && hasEnergy())
			return true;

		return false;

	}

	private boolean hasEnergy()
	{
		return energy > 0;
	}

	public void move(World world)
	{
		position.x = position.x + vel.x * getVelocityMod();
		position.y = position.y + vel.y * getVelocityMod();
		if (position.x < 0)
		{
			vel.x = -vel.x;
			position.x = 0;
		}
		if (position.x > world.extension.x)
		{
			vel.x = -vel.x;
			position.x = world.extension.x;
		}
		if (position.y < 0)
		{
			vel.y = -vel.y;
			position.y = 0;
		}
		if (position.y > world.extension.y)
		{
			vel.y = -vel.y;
			position.y = world.extension.y;
		}
		// System.out.println(position);
	}

	// Velocity depend by energy
	public double getVelocityMod()
	{
		return 2;// energy/50;
	}

	public boolean isInRadius(Food f)
	{
		if (position.squareDistance(f.position) < (radiusPeception * radiusPeception))
			return true;
		return false;
	}

	public boolean isInRadiusMouth(Food f)
	{
		if (position.squareDistance(f.position) < (9))
			return true;
		return false;
	}

	public void eat(Food f)
	{
		energy = energy + f.energy;
	}

	@Override
	public String toString()
	{
		return "Liso [energy=" + energy + ", position=" + position + ", vel=" + vel + ", age=" + age + "]\n";
	}

	public boolean isInRadius(Liso_0_1 l)
	{

		if (position.squareDistance(l.position) < (radiusPeception * radiusPeception))
			return true;
		return false;

	}

	public int getX()
	{
		return (int) position.x;
	}

	public int gety()
	{
		return (int) position.y;
	}

	public boolean conception(Liso_0_1 l2)
	{
		return conception(l2, 1.0);
	}

	// Prob is the prob of conception determianted by population of the world
	public boolean conception(Liso_0_1 l2, double prob)
	{
		if (this.isInRadius(l2))
		{
			if (this.energy > 60 && l2.energy > 60)
			{
				if (Math.random() < (l2.fertility * this.fertility) * prob)
				{
					this.energy = this.energy / 2;
					return true;
				}
			}
		}
		return false;
	}

	public boolean willEat(Food f)
	{
		if (this.energy > 400)// too full to eat
			return false;

		if (this.isInRadiusMouth(f))
		{
			return true;
		}
		return false;
	}

	public double getDailyEnergyConsume()
	{
		return dailyEnergyConsume;
	}

	public void setDailyEnergyConsume(double dailyEnergyConsume)
	{
		this.dailyEnergyConsume = dailyEnergyConsume;
	}

	public double getEnergy()
	{
		return energy;
	}

	public void setEnergy(double energy)
	{
		this.energy = energy;
	}

	public Coordinate getPosition()
	{
		return position;
	}

	public void setPosition(Coordinate position)
	{
		this.position = position;
	}

	public Coordinate getVel()
	{
		return vel;
	}

	public void setVel(Coordinate vel)
	{
		this.vel = vel;
	}

	public double getRadiusPeception()
	{
		return radiusPeception;
	}

	public void setRadiusPeception(double radiusPeception)
	{
		this.radiusPeception = radiusPeception;
	}

	public double getPerception()
	{
		return perception;
	}

	public void setPerception(double perception)
	{
		this.perception = perception;
	}

	public double getAge()
	{
		return age;
	}

	public void setAge(double age)
	{
		this.age = age;
	}

	public double getLisoLifeSpan()
	{
		return lisoLifeSpan;
	}

	public void setLisoLifeSpan(double lisoLifeSpan)
	{
		this.lisoLifeSpan = lisoLifeSpan;
	}

	public double getFertility()
	{
		return fertility;
	}

	public void setFertility(double fertility)
	{
		this.fertility = fertility;
	}

	public void foodAwarness(World world)
	{
		// TODO Auto-generated method stub

	}

	public boolean isAware(Food f)
	{
		if (this.energy > 400)// too full to eat
			return false;

		if (this.isInRadius(f))
		{
			if (Math.random() < this.perception)
			{
				return true;
			}
		}
		return false;
	}

	public void moveTowardFood(ArrayList<Food> fArray)
	{
		//select closest food
		double d = Double.MAX_VALUE;
		Food bestFood=null;
		for (Food f : fArray)
		{
			double distance = position.squareDistance(f.position);
			if (distance < d)
			{
				d = distance;
				bestFood = f;
			}
		}
		if (bestFood==null)
			return;
		
		//redirect Liso velocity Vector
		double x = bestFood.position.x - this.position.x;
		double y = bestFood.position.y - this.position.y;
		double hySquare = Math.sqrt(x * x + y * y);
		x = x / hySquare;
		y = y / hySquare;

		vel.x = x;
		vel.y = y;
	}

}
